#include <QVBoxLayout>
#include <QPushButton>
#include <QGroupBox>
#include <QFileDialog>
#include <QFileInfo>
#include <QtGui>
#include "preferencesdialog.h"

PreferencesDialog::PreferencesDialog(QWidget *parent)
        : QDialog(parent)
{
    this->setWindowIcon(QIcon(":/icons/preferences.svg"));
    QVBoxLayout *vbox = new QVBoxLayout(this);
    content = new QListWidget;
    content->setDragDropMode(QAbstractItemView::NoDragDrop);
    content->setViewMode(QListView::IconMode);
    content->setUniformItemSizes(true);
    content->setSelectionRectVisible(false);
    content->setIconSize(QSize(64, 64));
    content->setMovement(QListView::Static);
    content->setMaximumHeight(110);
    content->setSpacing(12);

    pages = new QStackedWidget;
    pages->addWidget(new GeoPage);
    pages->addWidget(new ShortcutsPage);
    pages->addWidget(new TagPage);

    connect(content,
            SIGNAL(currentRowChanged(int)),
            pages,
            SLOT(setCurrentIndex(int)));

    QDialogButtonBox *buttonBox = new QDialogButtonBox(QDialogButtonBox::Close,Qt::Horizontal,this);
    connect(buttonBox, SIGNAL(accepted()), this, SLOT(accept()));
    connect(buttonBox, SIGNAL(rejected()), this, SLOT(reject()));

    createIcons();

    vbox->addWidget(content);
    vbox->addWidget(pages,1);
    vbox->addWidget(buttonBox);

    content->setCurrentRow(0);
    //pages->setCurrentIndex(1);
    setWindowTitle(tr("qPhotoTag Preferences"));
}

void PreferencesDialog::createIcons()
{
     QListWidgetItem *geoButton = new QListWidgetItem(content);
     geoButton->setIcon(QIcon(":/icons/globe.svg"));
     //geoButton->setText(tr("Geocoding"));
     geoButton->setToolTip(tr("Geocoding preferences"));
     geoButton->setTextAlignment(Qt::AlignHCenter);
     geoButton->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled);
     geoButton->setSizeHint(QSize(64, 64));

     QListWidgetItem *shortcutsButton = new QListWidgetItem(content);
     shortcutsButton->setIcon(QIcon(":/icons/keyboard.svg"));
     //shortcutsButton->setText(tr("Shortcuts"));
     shortcutsButton->setToolTip(tr("Keyword shortcut configuration"));
     shortcutsButton->setTextAlignment(Qt::AlignHCenter);
     shortcutsButton->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled);
     shortcutsButton->setSizeHint(QSize(64, 64));

     QListWidgetItem *tagButton = new QListWidgetItem(content);
     tagButton->setIcon(QIcon(":/icons/tag.svg"));
     //tagButton->setText(tr("Tags"));
     tagButton->setToolTip(tr("Iptc/XMP keywords"));
     tagButton->setTextAlignment(Qt::AlignHCenter);
     tagButton->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled);
     tagButton->setSizeHint(QSize(64, 64));
}

GeoPage::GeoPage(QWidget *parent)
     : QWidget(parent)
{
    QGroupBox *wptGroup = new QGroupBox(tr("Waypoint file"));
    // first, read the settings and see if there is a saved .gpx file
    QString wpt_file_name = settings.value("waypointFile", QString("")).toString();
    if (wpt_file_name.isEmpty())
        wpt_file_name = QString(tr("none"));
    waypointLabel = new QLabel(wpt_file_name);
    QPushButton *browseButton = new QPushButton(tr("Browse..."), this);
    connect(browseButton, SIGNAL(clicked()), this, SLOT(selectWaypointFile()));

    QHBoxLayout *wptGroupLayout = new QHBoxLayout(wptGroup);
    wptGroupLayout->addWidget(waypointLabel);
    wptGroupLayout->addWidget(browseButton);

    QVBoxLayout *mainLayout = new QVBoxLayout;
    mainLayout->addWidget(wptGroup);
    mainLayout->addStretch(1);
    setLayout(mainLayout);

}

void GeoPage::selectWaypointFile()
{
    // select a .gpx file containing the waypoints
    QString wpt_file_name = QFileDialog::getOpenFileName(this, tr("Open GPX file"),
                                                         "", tr("GPX files (*.gpx *.GPX)"));
    if (! wpt_file_name.isEmpty() && QFileInfo(wpt_file_name).isReadable()) {
        settings.setValue("waypointFile", wpt_file_name);
        waypointLabel->setText(wpt_file_name);
    }
}

ShortcutsPage::ShortcutsPage(QWidget *parent)
        : QWidget(parent)
{
    QGroupBox *shortcutsGroup = new QGroupBox(tr("Keyboard shortcuts"), this);
    shortcutTree = new QTreeWidget(this);
    shortcutTree->setUniformRowHeights(true);
    shortcutTree->setAlternatingRowColors(true);
    shortcutTree->setIndentation(0);
    shortcutTree->setColumnCount(2);
    QTreeWidgetItem *___qtreewidgetitem = shortcutTree->headerItem();
    ___qtreewidgetitem->setText(0,tr("Shortcut"));
    ___qtreewidgetitem->setText(1,tr("IPTC tags"));
    connect(shortcutTree,
            SIGNAL(itemSelectionChanged()),
            this,
            SLOT(toggleRemoveButton()));
    QPushButton *addButton = new QPushButton(tr("Add"), this);
    connect(addButton,
            SIGNAL(clicked()),
            this,
            SLOT(addNewShortcut()));
    removeButton = new QPushButton(tr("Remove"), this);
    removeButton->setEnabled(false);
    connect(removeButton,
            SIGNAL(clicked()),
            this,
            SLOT(removeShortcut()));
    QHBoxLayout *buttonLayout = new QHBoxLayout;
    buttonLayout->addWidget(addButton);
    buttonLayout->addWidget(removeButton);
    QVBoxLayout *shortcutsGroupLayout = new QVBoxLayout(shortcutsGroup);
    shortcutsGroupLayout->addWidget(shortcutTree);
    shortcutsGroupLayout->addLayout(buttonLayout);

    QVBoxLayout *mainLayout = new QVBoxLayout();
    mainLayout->addWidget(shortcutsGroup);
    mainLayout->addStretch(1);
    setLayout(mainLayout);

    readShortcuts();
}

void ShortcutsPage::addNewShortcut()
{
    AddShortcutDialog addDlg(this);
    if (addDlg.exec() == QDialog::Accepted) {
        readShortcuts();
    }
}

void ShortcutsPage::removeShortcut()
{
    QString selectedShortcutText = shortcutTree->selectedItems().at(0)->text(0);
    for (int i = shortcuts.size() - 1; i >= 0; --i) {
        if (shortcuts.at(i).shortcut_text == selectedShortcutText)
            shortcuts.removeAt(i);
    }
    // save
    settings.beginWriteArray("shortcuts");
    for (int i = 0; i < shortcuts.size(); ++i) {
        settings.setArrayIndex(i);
        settings.setValue("key", shortcuts.at(i).key);
        settings.setValue("modifiers", shortcuts.at(i).modifiers);
        settings.setValue("shortcut_text", shortcuts.at(i).shortcut_text);
        settings.setValue("keywords", shortcuts.at(i).keywords);
    }
    settings.endArray();
    //re-read
    readShortcuts();
}

void ShortcutsPage::toggleRemoveButton()
{
    if (shortcutTree->selectedItems().size() > 0) {
        removeButton->setEnabled(true);
    } else {
        removeButton->setEnabled(false);
    }
}

void ShortcutsPage::readShortcuts()
{
    shortcuts.clear();
    int size = settings.beginReadArray("shortcuts");
    for (int i = 0; i < size; ++i) {
        settings.setArrayIndex(i);
        SHORTCUT shortcut;
        shortcut.key = settings.value("key").toInt();
        shortcut.modifiers = settings.value("modifiers").toUInt();
        shortcut.shortcut_text = settings.value("shortcut_text").toString();
        shortcut.keywords = settings.value("keywords").toString();
        shortcuts.append(shortcut);
    }
    settings.endArray();
    shortcutTree->clear();
    for (int i = 0; i < shortcuts.size(); ++i) {
        QStringList row;
        row.append(shortcuts.at(i).shortcut_text);
        row.append(shortcuts.at(i).keywords);
        QTreeWidgetItem *newqtreewidgetitem = new QTreeWidgetItem(row);
        shortcutTree->addTopLevelItem(newqtreewidgetitem);
    }
}

AddShortcutDialog::AddShortcutDialog(QWidget *parent)
        : QDialog(parent)
{
    QLabel *shortcutLabel = new QLabel(tr("Key combination:"));
    shortcutKey = new QLineEdit(this);
    shortcutKey->setReadOnly(true);
    QLabel *keywordsLabel = new QLabel(tr("IPTC keywords:"));
    keywords = new QLineEdit(this);
    connect(keywords,
            SIGNAL(textEdited(QString)),
            this,
            SLOT(keywordEdited()));

    QLabel *helpText = new QLabel(tr("In the \"Key combination\" box press the desired key combination,<br>"
                                     "and enter the desired IPTC keywords that should be added to the photos<br>"
                                     "when that key combination is pressed."));

    buttonBox = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel,Qt::Horizontal,this);
    connect(buttonBox, SIGNAL(accepted()), this, SLOT(accept()));
    connect(buttonBox, SIGNAL(rejected()), this, SLOT(reject()));

    buttonBox->button(QDialogButtonBox::Ok)->setEnabled(false);
    connect(keywords,
            SIGNAL(returnPressed()),
            buttonBox->button(QDialogButtonBox::Ok),
            SLOT(click()));
    connect(shortcutKey,
            SIGNAL(returnPressed()),
            buttonBox->button(QDialogButtonBox::Ok),
            SLOT(click()));

    QGridLayout *mainLayout = new QGridLayout();
    mainLayout->addWidget(shortcutLabel, 0, 0, 1, 1);
    mainLayout->addWidget(shortcutKey, 0, 1, 1, 1);
    mainLayout->addWidget(keywordsLabel, 1, 0, 1, 1);
    mainLayout->addWidget(keywords, 1, 1, 1, 1);
    mainLayout->addWidget(helpText, 2, 0, 1, 2);
    mainLayout->addWidget(buttonBox, 3, 0, 1, 2);
    setLayout(mainLayout);
}

void AddShortcutDialog::keywordEdited()
{
    if (! keywords->text().isEmpty() && ! shortcutKey->text().isEmpty()) {
        buttonBox->button(QDialogButtonBox::Ok)->setEnabled(true);
    } else {
        buttonBox->button(QDialogButtonBox::Ok)->setEnabled(false);
    }
}

void AddShortcutDialog::keyPressEvent(QKeyEvent *event)
{
    if (shortcutKey->hasFocus() && event->key() < 0xff) {
        shortcutKey->setText(modifierToString(event->nativeModifiers()) + QChar(event->key()));
        // enable the OK key if both fields are filled
        keywordEdited();
        shortcut.key = event->key();
        shortcut.modifiers = event->nativeModifiers();
        event->accept();
    } else {
        event->ignore();
    }
}

void AddShortcutDialog::accept()
{
    // save the data
    shortcut.keywords = keywords->text();
    shortcut.shortcut_text = shortcutKey->text();
    QList<SHORTCUT> shortcuts;
    // will be set to the position in the array if the shortcut key combo
    // already exists.
    int pos = -1;
    int size = settings.beginReadArray("shortcuts");
    for (int i = 0; i < size; ++i) {
        settings.setArrayIndex(i);
        SHORTCUT sc;
        sc.key = settings.value("key").toInt();
        sc.modifiers = settings.value("modifiers").toUInt();
        sc.shortcut_text = settings.value("shortcut_text").toString();
        if (sc.shortcut_text == shortcut.shortcut_text) {
            sc.keywords = shortcut.keywords;
            pos = i;
        } else {
            sc.keywords = settings.value("keywords").toString();
        }
        shortcuts.append(sc);
    }
    settings.endArray();
    if (pos < 0) {
        // append the new item
        shortcuts.append(shortcut);
    }
    // save
    settings.beginWriteArray("shortcuts");
    for (int i = 0; i < shortcuts.size(); ++i) {
        settings.setArrayIndex(i);
        settings.setValue("key", shortcuts.at(i).key);
        settings.setValue("modifiers", shortcuts.at(i).modifiers);
        settings.setValue("shortcut_text", shortcuts.at(i).shortcut_text);
        settings.setValue("keywords", shortcuts.at(i).keywords);
    }
    settings.endArray();
    QDialog::accept();
}

QString AddShortcutDialog::modifierToString(const quint32 modifiers)
{
    QString retval;
    retval.clear();
#ifdef Q_WS_MAC
    if (modifiers & 0x100) {
        if (! retval.isEmpty())
            retval += "+";
        retval += "cmd";          // ⌘
    }
    if (modifiers & 0x200) {
        if (! retval.isEmpty())
            retval += "+";
        retval += "shift";
    }
    if (modifiers & 0x800) {
        if (! retval.isEmpty())
            retval += "+";
        retval += "alt";          // ⌥
    }
    if (modifiers & 0x1000) {
        if (! retval.isEmpty())
            retval += "+";
        retval += "ctrl";
    }
#else
    if (modifiers & 1) {
        if (! retval.isEmpty())
            retval += "+";
        retval += "Shift";
    }
    if (modifiers & 4) {
        if (! retval.isEmpty())
            retval += "+";
        retval += "Ctrl";
    }
    if (modifiers & 8) {
        if (! retval.isEmpty())
            retval += "+";
        retval += "Alt";
    }
    if (modifiers & 128) {
        if (! retval.isEmpty())
            retval += "+";
        retval += "AltGr";
    }
#endif
    if (! retval.isEmpty())
        retval += "+";
    return retval;
}

TagPage::TagPage(QWidget *parent)
     : QWidget(parent)
{
    // read the settings
    QString saved_encoding_name = settings.value("iptcEncoding", QString("")).toString();
    int preferred_encoding = -1;
    bool saved_name_save = settings.value("saveEncodingName", true).toBool();
    bool saved_use_iptc = settings.value("useIPTC", true).toBool();
    bool saved_use_xmp = settings.value("useXMP", true).toBool();

    QGroupBox *formatGroup = new QGroupBox(tr("Keyword format"));
    use_iptc_cb = new QCheckBox(tr("Use IPTC for storing keywords"));
    use_iptc_cb->setChecked(saved_use_iptc);
    connect(use_iptc_cb,
            SIGNAL(stateChanged(int)),
            this,
            SLOT(saveSettings()));
    use_xmp_cb =  new QCheckBox(tr("Use XMP for storing keywords"));
    use_xmp_cb->setChecked(saved_use_xmp);
    connect(use_xmp_cb,
            SIGNAL(stateChanged(int)),
            this,
            SLOT(saveSettings()));

    QVBoxLayout *formatGroupLayout = new QVBoxLayout(formatGroup);
    formatGroupLayout->addWidget(use_iptc_cb);
    formatGroupLayout->addWidget(use_xmp_cb);

    QGroupBox *encGroup = new QGroupBox(tr("Encoding"));

    QStringList codecs;
    QList<int> mibs = QTextCodec::availableMibs();
    foreach (const int &mib, mibs) {
        QString codec = QLatin1String(QTextCodec::codecForMib(mib)->name());
        codecs.append(codec);
    }
    codecs.sort();
    for (int i = 0; i < codecs.size(); ++i) {
        if ( codecs.at(i) == saved_encoding_name )
            preferred_encoding = i;
    }
    QLabel *enc_label = new QLabel(tr("Select the preferred encoding for the IPTC data"));
    enc_combo = new QComboBox(this);
    enc_combo->addItems(codecs);
    if ( preferred_encoding >= 0 )
        enc_combo->setCurrentIndex(preferred_encoding);
    connect(enc_combo,
            SIGNAL(currentIndexChanged(int)),
            this,
            SLOT(saveSettings()));

    enc_name_save = new QCheckBox(tr("Save the encoding name to Iptc.Application2.SpecialInstructions"));
    enc_name_save->setChecked(saved_name_save);
    connect(enc_name_save,
            SIGNAL(stateChanged(int)),
            this,
            SLOT(saveSettings()));

    QVBoxLayout *encGroupLayout = new QVBoxLayout(encGroup);
    encGroupLayout->addWidget(enc_label);
    encGroupLayout->addWidget(enc_combo);
    encGroupLayout->addWidget(enc_name_save);

    QVBoxLayout *mainLayout = new QVBoxLayout;
    mainLayout->addWidget(formatGroup);
    mainLayout->addWidget(encGroup);
    mainLayout->addStretch(1);
    setLayout(mainLayout);

}

void TagPage::saveSettings()
{
    settings.setValue("iptcEncoding", enc_combo->currentText());
    settings.setValue("saveEncodingName", enc_name_save->isChecked());
    settings.setValue("useIPTC", use_iptc_cb->isChecked());
    settings.setValue("useXMP", use_xmp_cb->isChecked());
}
